#include "engine.h"

#include <GL/glfw.h>
#include <queue>

namespace HW
{

////Internal functions definitions
void _i_InitKeyMap ( void );
void GLFWCALL _i_OnKeyChange( int key, int action );
void GLFWCALL _i_OnChar( int character, int action );
void GLFWCALL _i_OnMouseButton( int button, int action );
void GLFWCALL _i_OnMouseMove( int x, int y );
void GLFWCALL _i_OnMouseWheel( int pos );
////Internal functions definitions

static std::queue<int> lCharQueue;
int lGlfw2LEKeyMap[GLFW_KEY_LAST+1];
short lKeyState[256];
short lMouseState[4];

int KeyHit(int key)
{
	int ans = lKeyState[key] & 2;
	lKeyState[key] &= 1;
	return (ans>0)?GL_TRUE:GL_FALSE;
}

int KeyDown(int key)
{
	return ((lKeyState[key]&1)>0)?GL_TRUE:GL_FALSE;
}

int GetChar(void)
{
	if ( lCharQueue.empty ( ) )
		return 0;

	int lans = lCharQueue.front ( );
	lCharQueue.pop ( );
	return lans;
}

void FlushKeys(void)
{
	while ( !lCharQueue.empty() )
		lCharQueue.pop();
	for ( int i = 0 ; i < 256 ; ++i )
		lKeyState[i] = 0;
}

int MouseHit(int button)
{
	int ans = lMouseState[button] & 2;
	lMouseState[button] &= 1;
	return (ans>0)?GL_TRUE:GL_FALSE;
}

int MouseDown(int button)
{
	return ((lMouseState[button]&1)>0)?GL_TRUE:GL_FALSE;
}

int MouseX(void)
{
	extern int gMouseX;
	return gMouseX;
}

int MouseY(void)
{
	extern int gMouseY;
	return gMouseY;
}

int MouseZ(void)
{
	extern int gMouseZ;
	return gMouseZ;
}

void MoveMouse(int x, int y)
{
	glfwSetMousePos ( x , y );
}

void HideMouse(void)
{
	glfwDisable ( GLFW_MOUSE_CURSOR );
}

void ShowMouse(void)
{
	glfwEnable ( GLFW_MOUSE_CURSOR );
}

void FlushMouse(void)
{
	for ( int i = 0 ; i < 4 ; ++i )
		lMouseState[i] = 0;
}

#include "glfw2LE_KeyMap.h"

void GLFWCALL _i_OnKeyChange( int key, int action )
{
	if ( action == GLFW_PRESS )
		lKeyState[lGlfw2LEKeyMap[key]] = 3;
	else
		lKeyState[lGlfw2LEKeyMap[key]] &= 2;
}

void GLFWCALL _i_OnChar( int character, int action )
{
	//TODO: consider keystroking here
	if ( action == GLFW_PRESS )
		lCharQueue.push ( character );
}

void GLFWCALL _i_OnMouseButton( int button, int action )
{
	++button;
	if ( action == GLFW_PRESS )
		lMouseState[button] = 3;
	else
		lMouseState[button] &= 2;
}

void GLFWCALL _i_OnMouseMove( int x, int y )
{
	extern int gMouseX, gMouseY;
	gMouseX = x;
	gMouseY = GraphicsHeight() - y;
}

void GLFWCALL _i_OnMouseWheel( int pos )
{
	extern int gMouseZ;
	gMouseZ = pos;
}

}